# coding: utf-8
import json, requests
import re
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db import models, transaction
from lib.common import BasicManager
from django.core.cache import cache
from services.datamodel.student.models import mm_Student, Student
from django.db.models import Q


class ModelManagerTiktokUser(BasicManager):

    def get_oauth_userinfo(self, open_id, access_token):
        """
        获取授权用户公开信息
        @param open_id: 授权用户唯一标识
        @param access_token: 授权token
        @return:
        """
        url = 'https://open.douyin.com/oauth/userinfo/'
        params = {
            'open_id': open_id,
            'access_token': access_token
        }
        try:
            r = requests.get(url=url, params=params)
            r.encoding = 'utf-8'
            result = json.loads(r.text)
            if int(result['data']['error_code']) == 0:
                return {'code': 0, 'data': result['data']}
            return {'code': 1, 'data': result}
        except Exception as e:
            return {'code': 1, 'data': e}

    def get_leads_user_detail(self, open_id, user_id, client_key, access_token=None):
        """
        获取意向用户详情
        @param open_id: 授权用户唯一标识
        @param access_token:  授权用户access_token
        @param user_id: 意向用户user_id
        @return:
        """
        try:
            if not access_token:
                result = self.refresh_access_token(client_key, open_id)
                if result['code'] != 0:
                    return result
                access_token = json.loads(result['data'])['access_token']
            url = f'https://open.douyin.com/enterprise/leads/user/detail/?open_id={open_id}&access_token={access_token}&user_id={user_id}'
            result = json.loads(requests.get(url=url).text)
            if result['data']['error_code'] != 0:
                return {'code': result['data']['error_code'], 'data': result}
            return {'code': 0, 'data': result['data']}
        except Exception as e:
            return {'code': 1, 'data': e}

    def refresh_access_token(self, client_key, open_id):
        """
        刷新access_token
        @param client_key: 应用唯一标识
        @param grant_type: 写死'refresh_token'
        @param refresh_token: 通过access_token获取到的refresh_token参数
        @param open_id: 用户唯一标识
        @return:
        """
        refresh_token = cache.get(f"{open_id}_refresh_token")
        if not refresh_token:
            return {'code': 1, 'data': 'refresh_token过期，重新授权'}
        try:
            # 刷新access_token
            url = f'https://open.douyin.com/oauth/refresh_token/?client_key={client_key}&grant_type=refresh_token&refresh_token={refresh_token}'
            r = json.loads(requests.get(url=url).text)
            if r['data']['error_code'] != 0:
                return {'code': r['data']['error_code'], 'data': r}
            expires_in = r['data']['expires_in']
            access_token = r['data']['access_token']
            cache.set(f'{open_id}_access_token', access_token, expires_in - 86400)
            # 刷新refresh_token
            result = self.refresh_refresh_token(client_key, refresh_token)
            if result['data']['error_code'] != 0:
                return {'code': result['data']['error_code'], 'data': result}
            refresh_token = result['data']['refresh_token']
            refresh_expires_in = result['data']['expires_in']
            cache.set(f'{open_id}_refresh_token', refresh_token, refresh_expires_in)
            return {'code': 0, 'data': r['data']}
        except Exception as e:
            return {'code': 1, 'data': e}

    def refresh_refresh_token(self, client_key, refresh_token):
        """
        刷新refresh_token
        @param client_key: 应用唯一标识
        @param refresh_token: 通过access_token获取到的refresh_token参数
        @param open_id: 用户唯一标识
        @return:
        """
        url = 'https://open.douyin.com/oauth/renew_refresh_token/'
        data = {
            'client_key': client_key,
            'refresh_token': refresh_token
        }
        r = json.loads(requests.post(url=url, data=data).text)
        return r


class ModelManagerTiktokPrivateLetter(BasicManager):

    def get_messages(self, page, is_assign, is_wx=None, is_phone=None, keyword=None, is_deal=None, is_wechat=None,
                     intention=None, headmaster_id=None, export=None, tiktokuser_id=None):
        res = self.filter(message_type='text', is_assign=is_assign).values(
            'id', 'tiktok_user__nick_name', 'content', 'nick_name', 'avatar', 'created_at', 'student__is_deal', 'student__intention',
            'student__headmaster__nick_name', 'student__studentchannel__is_wechat', 'is_assign', 'student_id', 'student__created_at'
        ).order_by("-created_at")
        if int(is_assign) == 1:  #已分配根据分配时间排序
            res = res.order_by("-student__created_at")
        if is_wx:
            if int(is_wx) == 1:
                res = res.filter(content__regex=r'[a-zA-Z0-9]{2,}')  # 匹配2个或2个以上由数字或字母组成的字符串
            if int(is_wx) == 0:
                res = res.exclude(content__regex=r'[a-zA-Z0-9]{2,}')
        if is_phone:
            if int(is_phone) == 1:
                res = res.filter(content__regex=r'1[3-9][0-9]{9}')  # 匹配11位手机号
            if int(is_phone) == 0:
                res = res.exclude(content__regex=r'1[3-9][0-9]{9}')
        if keyword:
            res = res.filter(content__contains=keyword)  # 匹配关键字
        if is_deal:
            res = res.filter(student__is_deal=is_deal)
        if is_wechat:
            if int(is_wechat) == 0:
                res = res.filter(Q(student__studentchannel__is_wechat=is_wechat) | Q(student__studentchannel__is_wechat=None))
            else:
                res = res.filter(student__studentchannel__is_wechat=is_wechat)
        if intention:
            res = res.filter(student__intention=intention)
        if headmaster_id:
            res = res.filter(student__headmaster_id=headmaster_id)
        if tiktokuser_id:
            res = res.filter(tiktok_user_id=tiktokuser_id)
        if export:
            from io import BytesIO
            from django.http import HttpResponse
            import xlwt
            ws = xlwt.Workbook(encoding="UTF-8")
            w = ws.add_sheet(u'数据')
            w.write(0, 0, u'头像')
            w.write(0, 1, u'昵称')
            w.write(0, 2, u'留言内容')
            w.write(0, 3, u'账户')
            w.write(0, 4, u'留言时间')
            w.write(0, 5, u'所属班主任')
            w.write(0, 6, u'用户意向')
            w.write(0, 7, u'是否加微')
            w.write(0, 8, u'是否成单')
            excel_row = 1
            for obj in res:
                w.write(excel_row, 0, obj['avatar'])
                w.write(excel_row, 1, obj['nick_name'])
                w.write(excel_row, 2, obj['content'])
                w.write(excel_row, 3, obj['tiktok_user__nick_name'])
                w.write(excel_row, 4, obj['created_at'])
                w.write(excel_row, 5, obj['student__headmaster__nick_name'])
                w.write(excel_row, 6, obj['student__intention'])
                w.write(excel_row, 7, obj['student__studentchannel__is_wechat'])
                w.write(excel_row, 8, obj['student__is_deal'])
                excel_row += 1
            sio = BytesIO()
            ws.save(sio)
            sio.seek(0)
            response = HttpResponse(sio.getvalue(), content_type='application/vnd.ms-excel')
            response['Content-Disposition'] = 'attachment; filename=stu_info.xls'
            response.write(sio.getvalue())
            return response
        paginator = Paginator(res, 15)
        try:
            result_page = paginator.page(page)
        except PageNotAnInteger:
            result_page = paginator.page(1)
        except EmptyPage as e:
            return {'retlist': [], 'curpageidx': page,
                    'hasnext': False, 'hasprevious': False}
        return {'lists': list(result_page), 'curpageidx': page,
                'hasnext': result_page.has_next(), 'hasprevious': result_page.has_previous(),
                'total_page': paginator.num_pages}

    def assign_headmaster(self, ids, headmaster_id):
        """分配班主任"""
        msg_list = self.filter(id__in=ids, is_assign=0).values()
        fail_ids = []  # 分配失败私信id
        success_ids = []  # 分配成功私信id
        for msg in msg_list:
            phones = re.findall(pattern=r'\d{11,}', string=msg['content'])
            if len(phones) != 1:
                fail_ids.append({'id': msg['id'], 'error': '私信中有多个手机号或无手机号，分配失败'})
                continue
            phone = phones[0]
            if len(phone) != 11:
                fail_ids.append({'id': msg['id'], 'error': '号码{}不是11位，分配失败'.format(phone)})
                continue
            try:
                with transaction.atomic():
                    state = mm_Student.add_student_if_not_exist(phone, openid='', avatar=msg['avatar'], channel=9)
                    student = state['user'].student
                    if state['newuser'] == 0 and student.headmaster:
                        fail_ids.append({'id': msg['id'], 'error': '号码{}已分配班主任，分配失败'.format(phone)})
                        continue
                    student.headmaster_id = headmaster_id
                    student.nick_name = msg['nick_name']
                    student.source = 1
                    student.save()
                    mm_TiktokPrivateLetter.filter(id=msg['id']).update(student=student, is_assign=1)
                    success_ids.append({'id': msg['id'], 'message': '号码{}分配班主任成功'.format(phone)})
            except Exception as e:
                fail_ids.append({'id': msg['id'], 'error': e})
        return {'fail_ids': fail_ids, 'success_ids': success_ids}


class TiktokUser(models.Model):
    province = models.CharField(max_length=30, null=True, blank=True, verbose_name='省份')
    city = models.CharField(max_length=30, null=True, blank=True, verbose_name='城市')
    country = models.CharField(max_length=30, null=True, blank=True, verbose_name='国家')
    nick_name = models.CharField(max_length=50, null=True, blank=True, verbose_name="昵称")  # 抖音昵称
    gender = models.CharField(max_length=7, choices=(('0', '未知'), ('1', '男'), ('2', '女')), default='0', verbose_name='性别')
    avatar = models.CharField(max_length=150, null=True, blank=True, verbose_name="头像")
    open_id = models.CharField(max_length=100, blank=True, null=True, unique=True, verbose_name="抖音openid")
    union_id = models.CharField(max_length=100, blank=True, null=True, verbose_name="抖音union_id", unique=True)
    oauth_status = models.PositiveSmallIntegerField(null=True, blank=True, default=0, verbose_name="授权状态")  # 0：未授权，1：授权
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    objects = ModelManagerTiktokUser()

    class Meta:
        verbose_name = '抖音用户授权表'
        verbose_name_plural = verbose_name
        db_table = "momself_tiktok_user"


class TiktokPrivateLetter(models.Model):
    tiktok_user = models.ForeignKey(TiktokUser, related_name='leters')
    event_type = models.PositiveSmallIntegerField(null=True, blank=True, default=0, verbose_name="事件类型")  # 0：接收私信
    message_type = models.CharField('消息类型', max_length=50)
    content = models.TextField('私信内容')
    nick_name = models.CharField(max_length=50, null=True, blank=True, verbose_name="私信用户昵称")
    avatar = models.CharField(max_length=150, null=True, blank=True, verbose_name="私信用户头像")
    user_id = models.CharField(max_length=100, blank=True, null=True, verbose_name="抖音私信用户user_id")
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_assign = models.PositiveSmallIntegerField(null=True, blank=True, default=0, verbose_name="是否分配班主任")  # 0：未分配，1：已分配
    student = models.ForeignKey(Student, null=True, blank=True, default=None)  # 分配后关联student表

    objects = ModelManagerTiktokPrivateLetter()

    class Meta:
        verbose_name = '抖音私信记录表'
        verbose_name_plural = verbose_name
        db_table = "momself_tiktok_private_latter"


mm_TiktokUser = TiktokUser.objects
mm_TiktokPrivateLetter = TiktokPrivateLetter.objects
